package com.example.demo.controller;

import com.example.demo.constant.Code;
import com.example.demo.enumeration.ItemStatus;
import com.example.demo.pojo.Result;
import com.example.demo.pojo.dto.*;
import com.example.demo.pojo.entity.Favourite;
import com.example.demo.pojo.entity.Follow;
import com.example.demo.pojo.entity.User;
import com.example.demo.pojo.entity.ViewHistory;
import com.example.demo.pojo.vo.ItemListVO;
import com.example.demo.pojo.vo.PageVO;
import com.example.demo.pojo.vo.UserDetailVO;
import com.example.demo.pojo.vo.UserProfileVO;
import com.example.demo.service.ItemService;
import com.example.demo.service.UserService;
import jakarta.validation.Valid;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
@Validated
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private ItemService itemService;

    @PostMapping("/register")
    public Result register(@RequestBody @Valid RegisterDTO registerDTO) {
        String phone = registerDTO.getPhone();

        if (!userService.validateVerificationCode(phone, registerDTO.getCode())) {
            return new Result(Code.REGISTER_ERR, null, "验证码错误或失效，请重试");
        }

        if (userService.checkPhoneExists(phone)) {
            return new Result(Code.REGISTER_ERR, null, "该电话号码已注册");
        }

        String name = registerDTO.getName();
        if (userService.checkNameExists(name)) {
            return new Result(Code.REGISTER_ERR, null, "该名称已存在");
        }

        String password = registerDTO.getPassword();

        boolean result = userService.register(phone, name, password, registerDTO.getStudentId(), registerDTO.getCampus());

        int code = (result) ? Code.REGISTER_OK : Code.REGISTER_ERR;
        String message = (result) ? "注册成功!" : "注册失败，请重试";

        if (result) {
            userService.deleteVerificationCode(phone);
        }

        return new Result(code, null, message);
    }

    @PostMapping("/login")
    public Result login(@RequestBody @Validated(ValidateGroup.Login.class) User user) {
        String phone = user.getPhone();

        User userSelectByPhone = userService.selectByPhone(phone);

        if (userSelectByPhone == null) {
            return new Result(Code.LOGIN_ERR, null, "该用户不存在");
        }

        String password = user.getPassword();

        if (!userService.checkPassword(phone, password)) {
            return new Result(Code.LOGIN_ERR, null, "密码错误，请重试");
        }

        String token = userService.generateUserToken(userSelectByPhone.getId());

        return new Result(Code.LOGIN_OK, token, "登录成功");
    }

    @PostMapping("/sms_login")
    public Result smsLogin(@RequestBody @Valid SmsLoginDTO smsLoginDTO) {
        String phone = smsLoginDTO.getPhone();

        User userSelectByPhone = userService.selectByPhone(phone);

        if (!userService.validateVerificationCode(phone, smsLoginDTO.getCode())) {
            return new Result(Code.LOGIN_ERR, null, "验证码错误或失效，请重试");
        }

        if (userSelectByPhone == null) {
            return new Result(Code.LOGIN_ERR, null, "该用户不存在");
        }

        String token = userService.generateUserToken(userSelectByPhone.getId());

        userService.deleteVerificationCode(phone);

        return new Result(Code.LOGIN_OK, token, "登录成功");
    }

    @PatchMapping("/forget_password")
    public Result forgetPassword(@RequestBody @Valid ForgetPasswordDTO forgetPasswordDTO) {
        String phone = forgetPasswordDTO.getPhone();

        User userSelectByPhone = userService.selectByPhone(phone);

        if (userSelectByPhone == null) {
            return new Result(Code.UPDATE_ERR, null, "该用户不存在");
        }

        String newPassword = forgetPasswordDTO.getNewPassword();
        String rePassword = forgetPasswordDTO.getRePassword();

        if (!newPassword.equals(rePassword)) {
            return new Result(Code.UPDATE_ERR, null, "两次输入的新密码不一致");
        }

        if (!userService.validateVerificationCode(phone, forgetPasswordDTO.getCode())) {
            return new Result(Code.UPDATE_ERR, null, "验证码错误或失效，请重试");
        }

        Long id = userSelectByPhone.getId();

        boolean result = userService.updatePassword(newPassword, id);

        int code = (result) ? Code.UPDATE_OK : Code.UPDATE_ERR;
        String message = (result) ? "修改密码成功！" : "修改密码失败, 请重试";

        if (result) {
            userService.deleteVerificationCode(phone);
            userService.deleteToken(id);
        }

        return new Result(code, null, message);
    }

    @GetMapping("/info")
    public Result currentUserInfo() {
        User currentUser = userService.getCurrentUser();

        return new Result(Code.SELECT_OK, currentUser, "查询成功");
    }

    @GetMapping("/profile")
    public Result currentUserProfile() {
        UserProfileVO currentUserProfile = userService.getCurrentUserProfile();

        return new Result(Code.SELECT_OK, currentUserProfile, "查询成功");
    }

    @GetMapping("/profile/{userId}")
    public Result getUserProfile(@PathVariable Long userId) {
        UserProfileVO userProfile = userService.getUserProfile(userId);

        int code = (userProfile != null) ? Code.SELECT_OK : Code.SELECT_ERR;
        String message = (userProfile != null) ? "查询成功" : "目标用户不存在";

        return new Result(code, userProfile, message);
    }

    @GetMapping("/detail/{userId}")
    public Result getUserDetail(@PathVariable Long userId) {
        UserDetailVO userDetail = userService.getUserDetail(userId);

        int code = (userDetail != null) ? Code.SELECT_OK : Code.SELECT_ERR;
        String message = (userDetail != null) ? "查询成功" : "目标用户不存在";

        return new Result(code, userDetail, message);
    }

    @PutMapping("/update_info")
    public Result updateInfo(@RequestBody @Validated(ValidateGroup.Crud.Update.class) User user) {
        String name = user.getName();

        String currentName = userService.getCurrentUser().getName();

        if (!currentName.equals(name) && userService.checkNameExists(name)) {
            return new Result(Code.UPDATE_ERR, null, "该名称已存在");
        }

        boolean result = userService.updateInfo(name, user.getCampus());

        int code = (result) ? Code.UPDATE_OK : Code.UPDATE_ERR;
        String message = (result) ? "更新成功！" : "更新失败, 请重试";

        return new Result(code, null, message);
    }

    @PatchMapping("/update_picture")
    public Result updatePicture(@RequestParam @URL String url) {
        boolean result = userService.updatePicture(url);

        int code = (result) ? Code.UPDATE_OK : Code.UPDATE_ERR;
        String message = (result) ? "更新成功！" : "更新失败, 请重试";

        return new Result(code, null, message);
    }

    @PatchMapping("/update_password")
    public Result updatePassword(@RequestBody @Valid UpdatePasswordDTO updatePasswordDTO) {
        String newPassword = updatePasswordDTO.getNewPassword();
        String rePassword = updatePasswordDTO.getRePassword();

        if (!newPassword.equals(rePassword)) {
            return new Result(Code.UPDATE_ERR, null, "两次输入的新密码不一致");
        }

        User currentUser = userService.getCurrentUser();
        String phone = currentUser.getPhone();

        if (!userService.checkPassword(phone, updatePasswordDTO.getOldPassword())) {
            return new Result(Code.UPDATE_ERR, null, "原密码错误");
        }

        Long id = currentUser.getId();

        boolean result = userService.updatePassword(newPassword, id);

        int code = (result) ? Code.UPDATE_OK : Code.UPDATE_ERR;
        String message = (result) ? "修改密码成功！" : "修改密码失败, 请重试";

        return new Result(code, null, message);
    }

    @PostMapping("/exit")
    public Result exit() {
        Long currentUserId = userService.getCurrentUserId();
        userService.deleteToken(currentUserId);

        return new Result(Code.EXIT_OK, null, "退出登录成功");
    }

    @PostMapping("/favourite")
    public Result addFavourite(@RequestBody @Valid Favourite favourite) {
        Long itemId = favourite.getItemId();

        ItemStatus status = itemService.selectStatusByItemId(itemId);

        if (status == null) {
            return new Result(Code.INSERT_ERR, null, "目标商品不存在");
        }

        if (status.equals(ItemStatus.pending) || status.equals(ItemStatus.rejected)) {
            return new Result(Code.INSERT_ERR, null, "目标商品未过审，不能添加收藏");
        }

        if (userService.selectFavouriteIdByIds(itemId) != null) {
            return new Result(Code.INSERT_ERR, null, "已添加该收藏，请勿重复添加");
        }

        boolean result = userService.addFavourite(itemId);

        int code = (result) ? Code.INSERT_OK : Code.INSERT_ERR;
        String message = (result) ? "添加收藏成功" : "添加收藏失败，请重试";

        return new Result(code, null, message);
    }

    @DeleteMapping("/favourite")
    public Result deleteFavourite(@RequestBody @Valid Favourite favourite) {
        Long itemId = favourite.getItemId();

        if (userService.selectFavouriteIdByIds(itemId) == null) {
            return new Result(Code.DELETE_ERR, null, "该收藏信息不存在");
        }

        boolean result = userService.deleteFavourite(itemId);

        int code = (result) ? Code.DELETE_OK : Code.DELETE_ERR;
        String message = (result) ? "删除收藏成功" : "删除收藏失败，请重试";

        return new Result(code, null, message);
    }

    @GetMapping("/favourite")
    public Result getFavouriteList() {
        List<ItemListVO> list = userService.getFavouriteList();

        return new Result(Code.SELECT_OK, list, "获取收藏列表成功");
    }

    @PostMapping("/follow")
    public Result addFollow(@RequestBody @Valid Follow follow) {
        Long currentUserId = userService.getCurrentUserId();
        Long followedId = follow.getFollowedId();

        if (currentUserId.equals(followedId)) {
            return new Result(Code.INSERT_ERR, null, "不能关注自己");
        }

        if (userService.selectNameById(followedId) == null) {
            return new Result(Code.INSERT_ERR, null, "目标用户不存在");
        }

        if (userService.selectFollowIdByIds(followedId) != null) {
            return new Result(Code.INSERT_ERR, null, "已关注该用户，请勿重复关注");
        }

        boolean result = userService.addFollow(followedId);

        int code = (result) ? Code.INSERT_OK : Code.INSERT_ERR;
        String message = (result) ? "添加关注成功" : "添加关注失败，请重试";

        return new Result(code, null, message);
    }

    @DeleteMapping("/follow")
    public Result deleteFollow(@RequestBody @Valid Follow follow) {
        Long followedId = follow.getFollowedId();

        if (userService.selectFollowIdByIds(followedId) == null) {
            return new Result(Code.DELETE_ERR, null, "该关注信息不存在");
        }

        boolean result = userService.deleteFollow(followedId);

        int code = (result) ? Code.DELETE_OK : Code.DELETE_ERR;
        String message = (result) ? "取消收藏成功" : "取消收藏失败，请重试";

        return new Result(code, null, message);
    }

    @GetMapping("/follow")
    public Result getFollowList() {
        List<UserProfileVO> list = userService.getFollowList();

        return new Result(Code.SELECT_OK, list, "获取关注列表成功");
    }

    @DeleteMapping("/view_history")
    public Result deleteViewHistory(@RequestBody @Valid ViewHistory viewHistory) {
        Long itemId = viewHistory.getItemId();

        Long currentUserId = userService.getCurrentUserId();
        Long viewHistoryId = userService.selectViewHistoryIdByIds(currentUserId, itemId);
        if (viewHistoryId == null) {
            return new Result(Code.DELETE_ERR, null, "该浏览记录不存在");
        }

        boolean result = userService.deleteViewHistory(itemId);

        int code = (result) ? Code.DELETE_OK : Code.DELETE_ERR;
        String message = (result) ? "删除浏览记录成功" : "删除浏览记录失败，请重试";

        return new Result(code, null, message);
    }

    @GetMapping("/view_history")
    public Result getViewHistoryList(@RequestParam(defaultValue = "1") int page) {
        PageVO viewHistory = userService.getViewHistory(page);

        return new Result(Code.SELECT_OK, viewHistory, "查询浏览记录成功");
    }
}